package de.hohenheim.view.mobile;

import java.util.ArrayList;
import java.util.Iterator;
import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.FigureUtilities;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;

import de.hohenheim.modell.State;
import de.hohenheim.view.constants.Constants;
import de.hohenheim.view.map.RoomMap;
import de.hohenheim.view.mobile.animation.AnimationFinishedQueueObserver;
import de.hohenheim.view.mobile.animation.Animator;
import de.hohenheim.view.mobile.animation.BusyForkTruckAnimator;
import de.hohenheim.view.mobile.animation.BusyForkTruckWaitAnimator;
import de.hohenheim.view.mobile.animation.LoadingAnimator;
import de.hohenheim.view.mobile.animation.RandomWalkAnimator;
import de.hohenheim.view.mobile.animation.WalkToAnimator;
import de.hohenheim.view.path.PathFigure;
import de.hohenheim.view.room.RoomFigure;

/**
 * @author Marc Fernandes
 * @version 1.0
 * 
 * This class represents a ForkTruck. To exist in the system a mobile object must 
 * be located in a RoomMap. This means either in a Room or on a Path between rooms.
 * 
 * When the mobileFigure Object is instantiated, this Object must be located in a room,
 * for example in the "entrance" of the RoomMap.
 */
public class ForkTruckFigure extends AnimationFigure {
	Image img = new Image(null,"img/stapler.gif");
	RoomFigure room = null;
	RoomFigure direction_to_room = null;
	PathFigure path = null;
	Animator currentAnimation = null;
	ArrayList<Animator> animationList = new ArrayList<Animator>();
	Iterator<Animator> animationIterator = animationList.iterator();
	boolean isLoaded=false;
	int max_load = 20;
	int actual_load = 0;
	boolean showBusy=false;
	int truck_id;
	
	/**
	 * Constructor. Sets the mobile object we want to create inside a room (as starting point)
	 * @param {@link RoomMap} map - The map where the figure should be placed. 
	 * @param RoomFigure The Room where the mobile object is located when it is instantiated.
	 * @param int id - a unique id for the fork truck. 
	 */
	public ForkTruckFigure(RoomMap map, RoomFigure in_room, int id, Object modellObject) {
		super(map,in_room, modellObject);
		this.truck_id=id;
		this.setFont(Constants.FORK_TRUCK_FONT);
	}	
	
	/**
	 * Returns the unique id of this fork truck.
	 * @return int
	 */
	public int getForkTruckId() {
		return this.truck_id;
	}
	/**
	 * If loaded is true, the mobile figure paints something that shows taht it is loaded.
	 * @param loaded - boolean
	 */
	public void setIsLoaded(boolean loaded) {
		this.isLoaded=loaded;
	}
	
	/**
	 * Gets the Maximum height in px of the load the figure paints.
	 * @return int - max_load 
	 */
	public int getMaxLoad() {
		return this.max_load;
	}
	
	/**
	 * Sets the height of the actual load. This method is used in an Animator to 
	 * draw periodically the increasing rectangle which represents the load status.
	 * @param load
	 */
	public void setActualLoad(int load) {
		this.actual_load=load;
		this.repaint();
	}
	
	/**
	 * Sets the busy indicator to true or false. This method is used by an animator, e.g. to draw a 
	 * blinking rectangle which indicates if the figure is busy/waiting.
	 * @param load
	 */
	public void showBusy(boolean busy) {
		this.showBusy=busy;
		this.repaint();
	}
	
	/**
	 * Returns the current state of the busy indicator. i.e. if the 
	 * busyindicator is visible in the moment or not. This method is used by an animator, e.g. to draw a 
	 * blinking rectangle which indicates if the figure is busy/waiting.
	 * @return boolean "isBusyRectangleVisible"
	 */
	public boolean isShowBusy() {
		return this.showBusy;
	}
	
	/**
	 * @see org.eclipse.draw2d.Figure#paintFigure(org.eclipse.draw2d.Graphics)
	 */
	public void paintFigure(Graphics g) {
	    Rectangle r = bounds;
	    g.setBackgroundColor(ColorConstants.green);
	    g.fillRectangle(r.x, r.y+max_load-actual_load, 10, actual_load);	    
	     
	    g.setForegroundColor(ColorConstants.white);	    
	    g.drawImage(img, r.x,r.y);
	    
	    Font f = this.getFont();
	    Dimension dim_text = FigureUtilities.getTextExtents(""+truck_id, f);
	    int x = r.width/2 - dim_text.width/2;
	    int y = r.height/2 - dim_text.height/2;
	    
	    g.drawText(""+truck_id,new Point(r.x+x+8, r.y+y+4));
	    if(showBusy) {
	    	g.setBackgroundColor(ColorConstants.red);
	    	g.fillRectangle(r.x+r.width-5, r.y+10, 5, 5);
	    }	   
	}
	
	/**
	 * An animation inside a RoomMap. Starts at the room, where the mobile object is actually located, 
	 * then randomly chooses a path which is connected to this room and walks to this room.
	 * In the Room the mobile object waits for a random time.
	 * From there it starts again. Endless looping... So no notification of Observers that the 
	 * Animation is finished.
	 * 	
	 */
	public void walkRandom() {
		RandomWalkAnimator anim = new RandomWalkAnimator(this.map, this);
	    currentAnimation=anim;
	}
	
	/**
	 * An animation from the current position to a room.
	 * The mobile object must be in a room or on a path which is connected to the room it wants to go.
	 * 
	 * @param RoomMap The RoomMap where the animation should be done.
	 * @param RoomFigure The Room the mobile object shall go.
	 */
	public void walkTo(RoomFigure room) {
		WalkToAnimator anim = new WalkToAnimator(this.map, this, room);	
		AnimationFinishedQueueObserver handler = new AnimationFinishedQueueObserver();
		anim.addObserver(handler);		
		addAnimation(anim);		
	}
	/**
	 * Starts an animation which loads the fork truck.
	 * 
	 * @param RoomMap The RoomMap where the animation should be done.
	 * @param int loading_time. The time the fork truck needs to load.
	 */
	public void load(int loading_time) {
		LoadingAnimator anim = new LoadingAnimator(this.map, this, loading_time, false);	
		AnimationFinishedQueueObserver handler = new AnimationFinishedQueueObserver();
		anim.addObserver(handler);		
		addAnimation(anim);		
		setIsLoaded(true);
	}
	/**
	 * Starts an animation which unloads the fork truck.
	 * 
	 * @param int loading_time. The time the fork truck needs to unload.
	 */
	public void unload(int loading_time) {
		LoadingAnimator anim = new LoadingAnimator(this.map, this, loading_time, true);	
		AnimationFinishedQueueObserver handler = new AnimationFinishedQueueObserver();
		anim.addObserver(handler);		
		addAnimation(anim);		
		setIsLoaded(false);
	}
	/**
	 * Starts an animation which shows that the fork truck is waiting/busy.
	 * Waits till the busy_time is over.
	 * @param int busy_time. The time the fork truck is waiting/busy.
	 */
	public void busy(int busy_time) {
		BusyForkTruckAnimator anim = new BusyForkTruckAnimator(this.map, this, busy_time);
		AnimationFinishedQueueObserver handler = new AnimationFinishedQueueObserver();
		anim.addObserver(handler);		
		addAnimation(anim);
	}		
	/**
	 * Starts an animation which shows that the fork truck is waiting/busy.
	 * Waits till the state object has the value UNBLOCKED.
	 * @param State state. The State of n object the fork truck is waiting for.
	 */
	public void waitFor(State state) {
		BusyForkTruckWaitAnimator anim = new BusyForkTruckWaitAnimator(this.map, this, state);
		AnimationFinishedQueueObserver handler = new AnimationFinishedQueueObserver();
		anim.addObserver(handler);		
		addAnimation(anim);
	}
	
}